package cn.workreport.modules.users.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.MD5;
import cn.workreport.constants.Constant;
import cn.workreport.modules.common.enums.IsEnum;
import cn.workreport.modules.common.exception.ServiceException;
import cn.workreport.modules.common.vo.PageVO;
import cn.workreport.modules.group.entity.Group;
import cn.workreport.modules.group.service.IGroupService;
import cn.workreport.modules.message.entity.Message;
import cn.workreport.modules.message.enums.MessageTypeEnum;
import cn.workreport.modules.message.service.IMessageService;
import cn.workreport.modules.organization.entity.Organization;
import cn.workreport.modules.organization.enums.OrgStatusEnum;
import cn.workreport.modules.organization.service.IOrganizationService;
import cn.workreport.modules.role.entity.Role;
import cn.workreport.modules.role.service.IRoleService;
import cn.workreport.modules.users.entity.UserEntity;
import cn.workreport.modules.users.mapper.UserMapper;
import cn.workreport.modules.users.po.UserPO;
import cn.workreport.modules.users.service.IUserExtendsService;
import cn.workreport.modules.users.service.IUserService;
import cn.workreport.modules.users.vo.CommonUserVO;
import cn.workreport.modules.users.vo.UserVO;
import cn.workreport.util.*;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class UserServiceImp extends ServiceImpl<UserMapper, UserEntity> implements IUserService {

    @Autowired
    private TokenUtil tokenUtil;

    @Autowired
    private IRoleService roleService;

    @Autowired
    private IOrganizationService organizationService;

    @Autowired
    private InitData initData;

    @Autowired
    private IGroupService groupService;

    @Autowired
    private IUserExtendsService userExtendsService;

    @Autowired
    private IMessageService messageService;

    @Override
    public JsonResult<?> reg(UserPO user) {
        // 根据参数user对象中的username属性查询用户数据。
        String username = user.getUsername();
        String password = user.getPassword();
        String nickname = user.getNickname();
        if (StrUtil.isBlank(username)) {
            return JsonResult.fail("用户名不能为空！");
        }
        if (StrUtil.isBlank(password)) {
            return JsonResult.fail("密码不能为空！");
        }
        if (StrUtil.isBlank(nickname)) {
            return JsonResult.fail("昵称不能为空！");
        }
        UserEntity result = baseMapper.findByUserName(username);
        // 判断查询结果是否不为null
        if (result != null) {
            // 是：根据用户名已经查询到数据，表示用户名已经被注册，则抛出UsernameDuplicateException对象
            return JsonResult.fail("用户名已被占用了！");
        }
        UserEntity userEntity = new UserEntity();
        // 此处不能直接复制 UserParams 中的属性，因为可能会修改不能设置的字段！
//        BeanUtil.copyProperties(
//                user,
//                userEntity,
//                // 复制旧的属性过来，忽略null属性，忽略null值，有值的以新的为主，null的则以旧为主
//                CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true)
//        );
        userEntity.setUsername(username);
        userEntity.setNickname(nickname);
        // 补全数据：加密后的密码，盐值
        // IdUtil ID工具类 randomUUID 获取随机uuid
        String salt = IdUtil.randomUUID().toUpperCase();
        System.err.println("salt = " + salt);
        // 可优化为一下方法
        // 参照 https://apidoc.gitee.com/dromara/hutool/
        MD5 md5 = new MD5(salt.getBytes(StandardCharsets.UTF_8), 5);
        String md5Password = md5.digestHex(password);
//        String md5Password = getMd5Password(password, salt);
        userEntity.setPassword(md5Password);
        userEntity.setSalt(salt);
        // 补全数据（不需要用户提交的）：deleted 、 role
        userEntity.setDeleted(IsEnum.NO);
        // 默认开启邮箱消息推送
        userEntity.setIsOpenEmailNotation(true);
        // 填充默认角色 -- 默认为 普通用户
//        Role hasRole = roleService.getEntityByName("普通用户");
//        if (ObjectUtil.isEmpty(hasRole)) {
//            throw new ServiceException("普通用户角色未创建，请联系管理员创建");
//        }
//        userEntity.setRoleId(hasRole.getId());
        // 调用userMapper的insert()方法执行注册，获取返回的受影响行数
        // mybatis-puls 自带方法 save 保存返回相应结果
        boolean insert = save(userEntity);
        // 判断受影响的行数是否不为1
        if (!insert) {
            // 是：表示注册失败，则抛出InsertException对象
            return JsonResult.fail("插入数据失败！");
        }
        System.out.println("\tuserEntity = " + userEntity);
        // 补全数据：4个日志属性
        // 用户自己注册，填充自己的id 和 用户名
        Date date = new Date();
        userEntity.setCreatorId(userEntity.getId());
        userEntity.setCreatorName(userEntity.getUsername());
        userEntity.setCreatedTime(date);
        userEntity.setModifierId(userEntity.getId());
        userEntity.setModifierName(userEntity.getUsername());
        userEntity.setModifiedTime(date);
        updateById(userEntity);
        return JsonResult.ok();
    }

    @Override
    public JsonResult<?> login(String username, String password, HttpServletRequest request) {
        // 请求参数校验
        if (StrUtil.isBlank(username)) {
            return JsonResult.fail("用户名不能为空！");
        }
        if (StrUtil.isBlank(password)) {
            return JsonResult.fail("密码不能为空！");
        }
        // 根据参数 username 查询用户的数据
        UserEntity user = baseMapper.findByUserName(username);
        if (user == null) {
            return JsonResult.fail("用户名不存在！");
        }
        // 判断查询结果中的 delete 是否为1
        if (user.getDeleted().equals(IsEnum.YES)) {
            // 是：用户数据标记为已删除
            return JsonResult.fail("用户数据不存在！");
        }
        // 从查询结果中取出salt值
        String salt = user.getSalt();
        // 将参数 password 加密，得到 md5Password
        MD5 md5 = new MD5(salt.getBytes(StandardCharsets.UTF_8), 5);
        String md5Password = md5.digestHex(password);
        // 判断查询结果中的 password 与以上加密得到的 md5Password 是否不同
        if (!user.getPassword().equals(md5Password)) {
            return JsonResult.fail("密码错误！");
        }
        // 保存当前登录token
//        String token = tokenUtil.createToken(user);
//        user.setToken(token);
        // 保存当前登录时间
        user.setLastLoginTime(new Date());
        // 获取客户端ip
        String loginIp = IpUtil.getIpAddress(request);
        log.info("获取客户端ip ===>" + loginIp);
        // 获取客户端的ip所在地
        if (StrUtil.isNotEmpty(loginIp)) {
            user.setLastLoginIp(loginIp);
            try {
                String addressByIp = IpUtil.getAddressByIp(loginIp);
                log.info("获取客户端的ip所在地 ===>" + addressByIp);
                user.setLastLoginArea(addressByIp);
            } catch (Exception e) {
                log.error("获取客户端的ip所在地失败！！！");
                e.printStackTrace();
            }
        }
        // 执行数据库修改
        boolean isSuccess = this.updateById(user);
        if (!isSuccess) {
            return JsonResult.fail("执行数据库修改失败！");
        }
        // 创建新的User对象，将查询结果中的指定字段封装到新的对象中
        UserVO newUser = getVoByEntity(user, true);
        return JsonResult.ok(newUser);
    }

    @Override
    public JsonResult<?> update(UserPO user) {
        LambdaUpdateWrapper<UserEntity> updateWrapper = Wrappers.<UserEntity>lambdaUpdate()
                .set(UserEntity::getNickname, user.getNickname())
                .set(UserEntity::getTruename, user.getTruename())
                .set(UserEntity::getGender, user.getGender())
                .set(UserEntity::getEmail, user.getEmail())
                .set(UserEntity::getPhone, user.getPhone())
                .set(UserEntity::getDescription, user.getDescription())
                .eq(UserEntity::getId, UserChacheFromToken.getUserId());
        // 执行数据库修改
        if (!this.updateByCondition(updateWrapper)) {
            return JsonResult.fail("更新失败");
        }
        return JsonResult.ok();
    }

    @Override
    public JsonResult<?> updatePassword(String oldPassword, String newPassword) {
        if (StrUtil.isBlank(oldPassword)) {
            return JsonResult.fail("原密码不能为空！");
        }
        if (StrUtil.isBlank(newPassword)) {
            return JsonResult.fail("新密码不能为空！");
        }
        // 取出当前登录用户信息
        UserEntity currentLoginUser = UserChacheFromToken.getUser();
        log.info("currentLoginUser ==> " + currentLoginUser);

        String salt = currentLoginUser.getSalt();
        MD5 md5 = new MD5(salt.getBytes(StandardCharsets.UTF_8), 5);
        String md5Password = md5.digestHex(oldPassword);
        log.info("md5Password ==> " + md5Password);

        if (!md5Password.equals(currentLoginUser.getPassword())) {
            return JsonResult.fail("原密码错误！");
        }
        String newMd5Password = md5.digestHex(newPassword);
        log.info("newMd5Password ==> " + newMd5Password);

        currentLoginUser.setPassword(newMd5Password);

//        UserEntity user = new UserEntity();
//        user.setPassword(newMd5Password);
//        BeanUtil.copyProperties(
//                currentLoginUser,
//                user,
//                // 复制旧的属性过来，忽略null属性，忽略null值，有值的以新的为主，null的则以旧为主
//                CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true)
//        );
//        log.info("user ==> ", user);
//        System.err.println(user);

        // 执行数据库修改
        boolean isSuccess = super.saveOrUpdate(currentLoginUser);
        if (!isSuccess) {
            return JsonResult.fail("操作失败！");
        }
        return JsonResult.ok("操作成功！");
    }

    @Override
    public JsonResult<?> updateAvatar(String avatar) {
        if (StrUtil.isBlank(avatar)) {
            return JsonResult.fail("头像不能为空！");
        }
        // 取出当前登录用户信息
        UserEntity currentLoginUser = UserChacheFromToken.getUser();
        log.info("currentLoginUser ==> " + currentLoginUser);
        // 设置新值
        currentLoginUser.setAvatar(avatar);
        // 执行数据库修改
        boolean isSuccess = super.saveOrUpdate(currentLoginUser);
        if (!isSuccess) {
            return JsonResult.fail("操作失败！");
        }
        UserVO newUserVO = getVoByEntity(currentLoginUser);
        return JsonResult.ok(newUserVO);
    }

    /**
     * 执行加密
     *
     * @param password 密码
     * @param salt     盐值
     * @return
     */
    private String getMd5Password(String password, String salt) {
        System.err.println("执行加密：");
        System.err.println("\t密码：" + password);
        System.err.println("\t盐值：" + salt);
        // 加密规则：
        // 1. 将盐值拼接在密码前后各一次
        // 2. 加密5次
        for (int i = 0; i < 5; i++) {
            password = DigestUtils.md5Hex(salt + password + salt);
        }
        System.err.println("结果：" + password);
        return password;
    }

    @Override
    public JsonResult<?> regByAdmin(UserPO user) {
        // 根据参数user对象中的username属性查询用户数据。
        String username = user.getUsername();
        String password = user.getPassword();
        String nickname = user.getNickname();
        if (StrUtil.isBlank(username)) {
            return JsonResult.fail("用户名不能为空！");
        }
        if (StrUtil.isBlank(password)) {
            return JsonResult.fail("密码不能为空！");
        }
        if (StrUtil.isBlank(nickname)) {
            return JsonResult.fail("昵称不能为空！");
        }
        UserEntity result = baseMapper.findByUserName(username);
        // 判断查询结果是否不为null
        if (result != null) {
            // 是：根据用户名已经查询到数据，表示用户名已经被注册，则抛出UsernameDuplicateException对象
            return JsonResult.fail("用户名已被占用了！");
        }
        UserEntity userEntity = new UserEntity();
        userEntity.setUsername(username);
        userEntity.setNickname(nickname);
        // 填充密码和盐值
        String salt = IdUtil.randomUUID().toUpperCase();
        MD5 md5 = new MD5(salt.getBytes(StandardCharsets.UTF_8), 5);
        String md5Password = md5.digestHex(password);
        userEntity.setPassword(md5Password);
        userEntity.setSalt(salt);
        // 填充默认角色 -- 默认为 普通用户
//        Role hasRole = roleService.getEntityByName("普通用户");
//        if (ObjectUtil.isEmpty(hasRole)) {
//            throw new ServiceException("普通用户角色未创建，请联系管理员创建");
//        }
//        userEntity.setRoleId(hasRole.getId());
        // 补全数据
        userEntity.setDeleted(IsEnum.NO);
        userEntity.setTruename(user.getTruename());
        userEntity.setPhone(user.getPhone());
        userEntity.setEmail(user.getEmail());
        userEntity.setGender(user.getGender());
        userEntity.setDescription(user.getDescription());
        // 如果是管理员添加新用户，则在此填充管理员id和用户名
        UserEntity currentLoginUser = UserChacheFromToken.getUser();
        System.out.println("\tregByAdmin => currentLoginUser " + currentLoginUser);
        Date date = new Date();
        userEntity.setCreatorId(currentLoginUser.getId());
        userEntity.setCreatorName(currentLoginUser.getUsername());
        userEntity.setCreatedTime(date);
        boolean insert = super.save(userEntity);
        // 判断受影响的行数是否不为1
        if (!insert) {
            return JsonResult.fail("插入数据失败！");
        }
        return JsonResult.ok();
    }

    @Override
    public JsonResult<?> updateByAdmin(UserPO user) {
        if (ObjectUtil.isEmpty(user.getId())) {
            return JsonResult.fail("用户 id 不能为空！");
        }
        LambdaUpdateWrapper<UserEntity> wrapper = Wrappers.<UserEntity>lambdaUpdate()
                .set(UserEntity::getNickname, user.getNickname())
                .set(UserEntity::getTruename, user.getTruename())
                .set(UserEntity::getGender, user.getGender())
                .set(UserEntity::getEmail, user.getEmail())
                .set(UserEntity::getPhone, user.getPhone())
                .set(UserEntity::getDescription, user.getDescription())
                .eq(UserEntity::getId, user.getId());
        // 执行数据库修改
        if (!this.updateByCondition(wrapper)) {
            return JsonResult.fail("更新失败");
        }
        return JsonResult.ok();
    }

    @Override
    public JsonResult<?> updateRoleByAdmin(Integer userId, Integer roleId) {
        // 必填参数校验
        if (ObjectUtil.isEmpty(userId)) {
            return JsonResult.fail("参数 userId 不能为空！");
        }
        if (ObjectUtil.isEmpty(roleId)) {
            return JsonResult.fail("参数 roleId 不能为空！");
        }
        // 查询是否存在该用户
        UserEntity userEntity = super.getById(userId);
        if (ObjectUtil.isEmpty(userEntity)) {
            return JsonResult.fail("该用户不存在");
        }
        // 查询是否存在该角色
        Role roleEntity = roleService.getById(roleId);
        if (ObjectUtil.isEmpty(roleEntity)) {
            return JsonResult.fail("该角色不存在");
        }
        // 自己不能修改自己的角色
        UserEntity loginUser = UserChacheFromToken.getUser();
        if (loginUser.getId().equals(userId)) {
            return JsonResult.fail("操作失败，不能修改自己的角色");
        }
        // 替换角色id
        userEntity.setRoleId(roleId);
        // 执行数据库修改
        if (!this.updateById(userEntity)) {
            throw new ServiceException("更新数据失败");
        }
        // 该用户信息发生了改变，给该用户发送通知，前端实时刷新用户信息
        Message message = new Message();
        message.setType(MessageTypeEnum.PERSONAL_MSG);
        message.setTitle("您已被授权角色为【" + roleEntity.getRoleName() + "】");
        messageService.sendMsgToUser(userEntity.getId(), message);
        return JsonResult.ok("操作成功！");
    }

    @Override
    public JsonResult<?> updatePasswordByAdmin(Integer userId, String newPassword) {
        // 必传参数校验
        if (ObjectUtil.isEmpty(userId)) {
            return JsonResult.fail("参数 userId 不能为空！");
        }
        if (StrUtil.isBlank(newPassword)) {
            return JsonResult.fail("参数 newPassword 不能为空！");
        }
        // 查询是否存在该用户
        UserEntity userEntity = super.getById(userId);
        if (ObjectUtil.isEmpty(userEntity)) {
            return JsonResult.fail("该用户不存在");
        }
        // 生成MD5密码
        String salt = userEntity.getSalt();
        MD5 md5 = new MD5(salt.getBytes(StandardCharsets.UTF_8), 5);
        String md5Password = md5.digestHex(newPassword);
        userEntity.setPassword(md5Password);
        // 执行数据库修改
        if (!this.saveOrUpdate(userEntity)) {
            return JsonResult.fail("操作失败！");
        }
        return JsonResult.ok("操作成功！");
    }

    @Override
    public JsonResult<?> toggleDeletedByAdmin(Integer userId, IsEnum deleted) {
        // 必传参数校验
        if (ObjectUtil.isEmpty(userId)) {
            return JsonResult.fail("参数 userId 不能为空！");
        }
        if (ObjectUtil.isEmpty(deleted)) {
            return JsonResult.fail("参数 newPassword 不能为空！");
        }
        // 不能停用自己
        if (userId.equals(UserChacheFromToken.getUserId())) {
            return JsonResult.fail("不能修改自己状态");
        }
        // 查询是否存在该用户
        UserEntity userEntity = super.getById(userId);
        if (ObjectUtil.isEmpty(userEntity)) {
            return JsonResult.fail("该用户不存在");
        }
        // 修改 deleted 字段
        userEntity.setDeleted(deleted);
        // 执行数据库修改
        if (!super.saveOrUpdate(userEntity)) {
            return JsonResult.fail("操作失败！");
        }
        return JsonResult.ok("操作成功！");
    }

    @Override
    public JsonResult<?> updateUsersGroup(List<Integer> userIds, Integer groupId, Integer leaderId, Integer orgId) {
        if (ObjectUtil.isEmpty(groupId)) {
            return JsonResult.fail("缺少参数 groupId");
        }
        if (ObjectUtil.isEmpty(orgId)) {
            return JsonResult.fail("缺少参数 orgId");
        }
        Organization org = this.organizationService.getById(orgId);
        if (ObjectUtil.isEmpty(org)) {
            return JsonResult.fail("该机构不存在");
        }
        // 查出该机构的管理员id
        Integer currentOrgManagerId = org.getOrgManagerId();
        Role groupManageRole = roleService.getEntityByName(
                InitData.InitRoleNameEnum.GROUP_MANAGER.getRoleName(), orgId
        );
        Role normalRole = roleService.getEntityByName(
                InitData.InitRoleNameEnum.NORMAL_ROLE.getRoleName(), orgId
        );
        if (ObjectUtil.isEmpty(groupManageRole) || ObjectUtil.isEmpty(normalRole)) {
            return JsonResult.fail("修改失败，获取角色信息失败");
        }

        // 如果为 userIds 空，则清空组织成员
        if (ObjectUtil.isEmpty(userIds)) {
            List<UserEntity> userList = getUserListByGroupId(groupId);
            log.info("如果为 userIds 空，则清空组织成员 > userList" + userList);
            if (!ObjectUtil.isEmpty(userList)) {
                for (UserEntity userEntity : userList) {
                    userEntity.setGroupId(null);
                    userEntity.setIsLeader(false);
                    if (!userEntity.getId().equals(currentOrgManagerId)) {
                        userEntity.setRoleId(normalRole.getId());
                    }
                }
                boolean isSuccess = updateBatchById(userList);
                if (!isSuccess) {
                    return JsonResult.fail("操作失败！");
                }
            }
        }
        // 如果为 userIds 不为空，添加成员
        else {
            // 组长不能为空
            if (ObjectUtil.isEmpty(leaderId)) {
                return JsonResult.fail("缺少参数 leaderId");
            }
            // 找出原来的所有成员列表
            List<UserEntity> originMemberList = getUserListByGroupId(groupId);
            // 查出现在的成员列表
            List<UserEntity> nowUserList = listByIds(userIds);
            log.info("userIds 不为空 现在的成员 > nowUserList" + nowUserList);
            for (UserEntity userEntity : nowUserList) {
                // 现在的成员关联上组织id
                userEntity.setGroupId(groupId);
                // 如果是组长则设置 isLeader 为 true
                if (leaderId.equals(userEntity.getId())) {
                    userEntity.setIsLeader(true);
                    if (!userEntity.getId().equals(currentOrgManagerId)) {
                        // 赋予组长角色
                        userEntity.setRoleId(groupManageRole.getId());
                    }
                    // 给他发送一则消息
                    Message message = new Message();
                    message.setType(MessageTypeEnum.PERSONAL_MSG);
                    message.setTitle("恭喜您成为了新的组织管理员");
                    messageService.sendMsgToUser(userEntity.getId(), message);
                } else {
                    userEntity.setIsLeader(false);
                    if (!userEntity.getId().equals(currentOrgManagerId)) {
                        userEntity.setRoleId(normalRole.getId());
                    }
                }
            }
            // 找出不包含现在成员的人，重置清空他们的 groupId 和 isLeader
            Set<Integer> nowUserIds = nowUserList.stream().map(UserEntity::getId).collect(Collectors.toSet());
            List<UserEntity> newUserList = originMemberList.stream()
                    .filter(item -> !nowUserIds.contains(item.getId()))
                    .map(item ->
                    {
                        item.setGroupId(null);
                        item.setIsLeader(false);
                        if (!item.getId().equals(currentOrgManagerId)) {
                            item.setRoleId(normalRole.getId());
                        }
                        return item;
                    }).collect(Collectors.toList());
            // 合并所有需要修改的人
            newUserList.addAll(nowUserList);
            log.info("newUserList ===>" + newUserList);
            // 执行数据库修改
            if (!ObjectUtil.isEmpty(newUserList)) {
                boolean isSuccess = updateBatchById(newUserList);
                if (!isSuccess) {
                    return JsonResult.fail("操作失败！");
                }
            }
        }
        return JsonResult.ok("操作成功！");
    }

    @Override
    public JsonResult<?> userBindOrg(Integer orgId, String verifyAnswer) {
        if (ObjectUtil.isEmpty(orgId)) {
            return JsonResult.fail("缺少参数 orgId");
        }
        UserEntity loginUser = UserChacheFromToken.getUser();
        // 如果当前用户已经绑定了机构
        if (!ObjectUtil.isEmpty(loginUser.getOrgId())) {
            return JsonResult.fail("您已经加入过机构，请先解除再绑定");
        }
        // 检查机构是否可加入
        Organization org = organizationService.getById(orgId);
        if (ObjectUtil.isEmpty(org)) {
            return JsonResult.fail("该机构不存在");
        }
        if (OrgStatusEnum.DISABLED == org.getOrgStatus()) {
            return JsonResult.fail("该机构已经暂停使用");
        }
        if (IsEnum.NO == org.getCanJoin()) {
            return JsonResult.fail("该机构设置不可加入");
        }
        // 若机构开启验证
        if (IsEnum.YES == org.getIsOpenVerification()) {
            if (ObjectUtil.isEmpty(verifyAnswer)) {
                return JsonResult.fail("该机构开启验证，缺少参数 verifyAnswer");
            }
            if (!verifyAnswer.equals(org.getVerifyAnswer())) {
                return JsonResult.fail("验证失败，答案错误");
            }
        }
        loginUser.setOrgId(orgId);

        // 如果当前用户是机构管理员，填充机构管理员角色
        if (loginUser.getId().equals(org.getOrgManagerId())) {
            Role orgManagerRole = roleService.getEntityByName(InitData.InitRoleNameEnum.ORG_MANAGER.getRoleName(), orgId);
            if (ObjectUtil.isEmpty(orgManagerRole)) {
                return JsonResult.fail("关联失败，初始化机构管理员角色不存在");
            }
            loginUser.setRoleId(orgManagerRole.getId());
        }
        // 如果当前用户不是是机构管理员，填充默认角色普通用户
        else {
            Role normalRole = roleService.getEntityByName(InitData.InitRoleNameEnum.NORMAL_ROLE.getRoleName(), orgId);
            if (ObjectUtil.isEmpty(normalRole)) {
                return JsonResult.fail("关联失败，初始化普通用户角色不存在");
            }
            loginUser.setRoleId(normalRole.getId());
            // 给机构管理员发送一则消息
            Message message = new Message();
            message.setType(MessageTypeEnum.SYSTEM_MSG);
            String currentLoginUserName = ObjectUtil.isEmpty(loginUser.getTruename()) ? loginUser.getNickname() : loginUser.getTruename();
            message.setTitle("用户【" + currentLoginUserName + "】加入了您的机构");
            messageService.sendMsgToUser(org.getOrgManagerId(), message);
        }

        loginUser.setBindOrgTime(new Date());

        // 执行关联
        if (!saveOrUpdate(loginUser)) {
            throw new ServiceException("更新数据失败");
        }

        // 更新用户补充信息的绑定机构的时间（最新的一次）
//        UserExtends userExtends = this.userExtendsService.getByUserId(loginUser.getId());
//        if (ObjectUtil.isEmpty(userExtends)) {
//            userExtends = new UserExtends();
//            userExtends.setUserId(loginUser.getId());
//        }
//        userExtends.setBindOrgTime(new Date());
//        this.userExtendsService.saveOrUpdate(userExtends);

        // 返回前端用户信息VO
        UserVO newUserVO = getVoByEntity(loginUser, true);
        return JsonResult.ok(newUserVO);
    }

    @Override
    public List<UserEntity> listByRoleId(Integer roleId) {
        if (ObjectUtil.isEmpty(roleId)) {
            return null;
        }
        LambdaQueryWrapper<UserEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserEntity::getRoleId, roleId);
        wrapper.orderByDesc(UserEntity::getCreatedTime);
        return list(wrapper);
    }

    @Override
    public List<UserEntity> listByOrgId(Integer orgId) {
        if (ObjectUtil.isEmpty(orgId)) {
            return null;
        }
        LambdaQueryWrapper<UserEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserEntity::getOrgId, orgId);
        wrapper.orderByDesc(UserEntity::getCreatedTime);
        return list(wrapper);
    }

    @Override
    public JsonResult<?> listHasNotGroupUser(Integer orgId) {
        if (ObjectUtil.isEmpty(orgId)) {
            return JsonResult.fail("参数 orgId 不能为空");
        }
        LambdaQueryWrapper<UserEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.isNull(UserEntity::getGroupId);
        wrapper.eq(UserEntity::getOrgId, orgId);
        wrapper.orderByDesc(UserEntity::getCreatedTime);
        List<UserEntity> userList = list(wrapper);
        List<CommonUserVO> userVOList = userList.stream().map(userEntity -> {
            CommonUserVO userVO = new CommonUserVO();
            BeanUtil.copyProperties(
                    userEntity,
                    userVO,
                    // 复制旧的属性过来，忽略null属性，忽略null值，有值的以新的为主，null的则以旧为主
                    CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true)
            );
            return userVO;
        }).collect(Collectors.toList());
        return JsonResult.ok(userVOList);
    }

    @Override
    public JsonResult<?> preparedData() {
        Map<String, Object> data = new HashMap<>();
        // 删除状态
        List<Map<String, Object>> deletedSelectList = EnumUtil.getSelectList(IsEnum.class);
        data.put("deletedSelectList", deletedSelectList);
        return JsonResult.ok(data);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public JsonResult<?> userUnboundOrg(Integer orgId) {
        if (ObjectUtil.isEmpty(orgId)) {
            return JsonResult.fail("缺少参数 orgId");
        }
        Organization org = this.organizationService.getById(orgId);
        if (ObjectUtil.isEmpty(org)) {
            return JsonResult.fail("解除关联的机构不存在");
        }
        UserEntity loginUser = UserChacheFromToken.getUser();

        // 如果当前用户是机构管理员
        if (loginUser.getId().equals(org.getOrgManagerId())) {
            // 查出关联该机构最早的人
            LambdaQueryWrapper<UserEntity> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(UserEntity::getOrgId, orgId);
            queryWrapper.ne(UserEntity::getId, loginUser.getId());
            queryWrapper.orderByAsc(UserEntity::getBindOrgTime);
            queryWrapper.last(" limit 1 ");
            UserEntity newManager = this.getOne(queryWrapper, false);
            if (ObjectUtil.isNotEmpty(newManager)) {
                // 把机构管理员转给他
                Role orgManagerRole = this.roleService.getEntityByName(
                        InitData.InitRoleNameEnum.ORG_MANAGER.getRoleName(), orgId
                );
                if (ObjectUtil.isNotEmpty(orgManagerRole)) {
                    // 更改新的用户角色
                    LambdaUpdateWrapper<UserEntity> updateWrapper = Wrappers.lambdaUpdate();
                    updateWrapper.set(UserEntity::getRoleId, orgManagerRole.getId());
                    updateWrapper.eq(UserEntity::getId, newManager.getId());
                    if (!this.updateByCondition(updateWrapper)) {
                        throw new ServiceException("更新数据失败[1]");
                    }
                    // 更改机构信息的管理人id
                    LambdaUpdateWrapper<Organization> updateWrapper1 = Wrappers.lambdaUpdate();
                    updateWrapper1.set(Organization::getOrgManagerId, newManager.getId());
                    updateWrapper1.eq(Organization::getId, orgId);
                    if (!this.organizationService.updateByCondition(updateWrapper1)) {
                        throw new ServiceException("更新数据失败[2]");
                    }
                    // 给他发送一则消息
                    Message message = new Message();
                    message.setType(MessageTypeEnum.PERSONAL_MSG);
                    message.setTitle("恭喜您成为了新的机构管理员");
                    messageService.sendMsgToUser(newManager.getId(), message);
                }
            }
            // 如果没有其他人员了，删除该机构，结束
            else {
                return this.organizationService.removeByIdEntity(orgId);
            }
        } else {
            // 给机构管理员发送一则消息
            Message message = new Message();
            message.setType(MessageTypeEnum.SYSTEM_MSG);
            String currentLoginUserName = ObjectUtil.isEmpty(loginUser.getTruename()) ? loginUser.getNickname() : loginUser.getTruename();
            message.setTitle("用户【" + currentLoginUserName + "】退出了您的机构");
            messageService.sendMsgToUser(org.getOrgManagerId(), message);
        }
        // 如果已经关联了组织
        Integer userGroupId = loginUser.getGroupId();
        if (ObjectUtil.isNotEmpty(userGroupId)) {
            Group userGroup = this.groupService.getById(userGroupId);
            if (ObjectUtil.isNotEmpty(userGroup)) {
                // 如果当前用户是组长
                if (ObjectUtil.isNotEmpty(loginUser.getIsLeader()) && loginUser.getIsLeader()) {
                    // 查询该组织的成员列表
                    List<UserEntity> groupMemberList = this.getUserListByGroupId(userGroupId);
                    // 筛选出除了当前用户的用户列表
                    List<UserEntity> restMemberList = groupMemberList.stream()
                            .filter(item -> !item.getId().equals(loginUser.getId()))
                            .collect(Collectors.toList());
                    // 如果不为空，选第一个作为组长
                    if (ObjectUtil.isNotEmpty(restMemberList)) {
                        Role groupManageRole = this.roleService.getEntityByName(
                                InitData.InitRoleNameEnum.GROUP_MANAGER.getRoleName(), orgId
                        );
                        UserEntity newGroupLeader = restMemberList.get(0);
                        newGroupLeader.setIsLeader(true);
                        // 赋予组长角色
//                        newGroupLeader.setRoleId(groupManageRole.getId());
                        if (!this.saveOrUpdate(newGroupLeader)) {
                            throw new ServiceException("更新数据失败[3]");
                        }
                        // 给他发送一则消息
                        Message message = new Message();
                        message.setType(MessageTypeEnum.PERSONAL_MSG);
                        message.setTitle("您成为了【" + userGroup.getGroupName() + "】的组织管理员");
                        messageService.sendMsgToUser(newGroupLeader.getId(), message);
                    }
                }
            }
        }
        loginUser.setOrgId(null);
        loginUser.setGroupId(null);
        loginUser.setIsLeader(false);
        if (!this.updateById(loginUser)) {
            throw new ServiceException("更新数据失败[4]");
        }
        return JsonResult.ok();
    }

    @Override
    public Integer countMemberByOrgId(Integer orgId) {
        if (ObjectUtil.isEmpty(orgId)) {
            return 0;
        }
        LambdaQueryWrapper<UserEntity> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(UserEntity::getOrgId, orgId);
        return this.count(queryWrapper);
    }

    @Override
    public void wrapEntity(UserEntity entity) {
        // 【性别】中文显示
        if (!ObjectUtils.isEmpty(entity.getGender())) {
            String genderLabel = entity.getGender().getLabel();
            entity.setGenderLabel(genderLabel);
        }
        // 【是否停用】中文显示
        if (!ObjectUtils.isEmpty(entity.getDeleted())) {
            String deletedLabel = entity.getDeleted().getLabel();
            entity.setDeletedLabel(deletedLabel);
        }
        // 重要的数据不返回
        entity.setPassword(null);
        entity.setSalt(null);
        entity.setToken(null);
    }

    @Override
    public PageVO<UserEntity> pageEntity(IPage<UserEntity> page, Wrapper<UserEntity> queryWrapper) {
        IPage<UserEntity> pageResult = this.page(page, queryWrapper);
        List<UserEntity> userEntityList = pageResult.getRecords();
        if (ObjectUtil.isNotEmpty(userEntityList)) {
            userEntityList.forEach(this::wrapEntity);

            // 【所属机构】中文显示
            Set<Integer> orgIdSet = userEntityList.stream().map(UserEntity::getOrgId).collect(Collectors.toSet());
            if (ObjectUtil.isNotEmpty(orgIdSet)) {
                List<Organization> orgList = this.organizationService.listByIds(orgIdSet);
                if (ObjectUtil.isNotEmpty(orgList)) {
                    Map<Integer, String> orgMap = orgList.stream()
                            .collect(Collectors.toMap(Organization::getId, Organization::getOrgName, (last, next) -> next));
                    log.info("orgMap ====>" + orgMap);
                    userEntityList.forEach(item -> {
                        if (ObjectUtil.isNotEmpty(item.getOrgId())) {
                            item.setOrgName(orgMap.get(item.getOrgId()));
                        }
                    });
                }
            }

            // 【角色】中文显示
            Set<Integer> roleIdSet = userEntityList.stream().map(UserEntity::getRoleId).collect(Collectors.toSet());
            if (ObjectUtil.isNotEmpty(roleIdSet)) {
                List<Role> roleList = this.roleService.listByIds(roleIdSet);
                if (ObjectUtil.isNotEmpty(roleList)) {
                    Map<Integer, String> roleMap = roleList.stream()
                            .collect(Collectors.toMap(Role::getId, Role::getRoleName, (last, next) -> next));
                    log.info("roleMap ====>" + roleMap);
                    userEntityList.forEach(item -> {
                        if (ObjectUtil.isNotEmpty(item.getRoleId())) {
                            item.setRoleName(roleMap.get(item.getRoleId()));
                        }
                    });
                }
            }

            // 【组织】中文显示
            Set<Integer> groupIdSet = userEntityList.stream().map(UserEntity::getGroupId).collect(Collectors.toSet());
            if (ObjectUtil.isNotEmpty(groupIdSet)) {
                List<Group> groupList = this.groupService.listByIds(groupIdSet);
                if (ObjectUtil.isNotEmpty(groupList)) {
                    Map<Integer, String> groupMap = groupList.stream()
                            .collect(Collectors.toMap(Group::getId, Group::getGroupName, (last, next) -> next));
                    log.info("groupMap ====>" + groupMap);
                    userEntityList.forEach(item -> {
                        if (ObjectUtil.isNotEmpty(item.getGroupId())) {
                            item.setGroupName(groupMap.get(item.getGroupId()));
                        }
                    });
                }
            }

        }
        return new PageVO<>(pageResult);
    }

    @Override
    public UserEntity getByIdEntity(Integer id) {
        UserEntity entity = this.getById(id);
        return entity;
    }

    @Override
    public JsonResult<?> saveOrUpdateEntity(UserEntity entity) {
        return null;
    }

    @Override
    public JsonResult<?> removeByIdEntity(Integer id) {
        return null;
    }

    @Override
    public JsonResult<?> removeByIdsEntity(List<Integer> ids) {
        return null;
    }

    public UserVO getVoByEntity(UserEntity userEntity) {
        return getVoByEntity(userEntity, false);
    }
    public UserVO getVoByEntity(UserEntity userEntity, boolean isRefreshToken) {
        if (ObjectUtils.isEmpty(userEntity)) {
            return null;
        }
        Role userRole = null;
        // 创建新的UserVO对象，将查询结果中的指定字段封装到新的对象中
        UserVO newUser = new UserVO();
        BeanUtil.copyProperties(
                userEntity,
                newUser,
                // 复制旧的属性过来，忽略null属性，忽略null值，有值的以新的为主，null的则以旧为主
                CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true)
        );

        // 查询用户角色名称
        if (!ObjectUtils.isEmpty(newUser.getIsSupperAdmin()) && newUser.getIsSupperAdmin()) {
            newUser.setRoleName(Constant.SUPER_ADMIN_ROLE_NAME);
        } else {
            if (!ObjectUtil.isEmpty(userEntity.getRoleId())) {
                userRole = roleService.getByIdEntity(userEntity.getRoleId());
                if (!ObjectUtil.isEmpty(userRole)) {
                    newUser.setRoleName(userRole.getRoleName());
                    log.info("userRole ===>" + userRole);
                    newUser.setPermissions(userRole.getPermissions());
//                    newUser.setPermissions(userRole.getPermissions().stream().map(item -> item.getValue()).collect(Collectors.toList()));
                }
            }
        }

        // 查询机构名称
        if (!ObjectUtil.isEmpty(userEntity.getOrgId())) {
            Organization org = organizationService.getById(userEntity.getOrgId());
            if (!ObjectUtil.isEmpty(org)) {
                newUser.setOrgName(org.getOrgName());
            }
        }
        if (isRefreshToken) {
            String token = tokenUtil.createToken(userEntity, userRole);
            // 把旧的 token 移除
//            logout();
            newUser.setToken(token);
        }
        return newUser;
    }

    @Override
    public JsonResult<?> userBindGroup(Integer userId, Integer groupId) {
        if (ObjectUtil.isEmpty(userId)) {
            return JsonResult.fail("缺少参数 userId");
        }
        if (ObjectUtil.isEmpty(groupId)) {
            return JsonResult.fail("缺少参数 groupId");
        }
        // 判断用户是否存在
        UserEntity userEntity = this.getById(userId);
        if (ObjectUtil.isEmpty(userEntity)) {
            return JsonResult.fail("该用户数据不存在");
        }
        // 判断用户是否已经绑定了组织
        if (ObjectUtil.isNotEmpty(userEntity.getGroupId())) {
            return JsonResult.fail("该用户已经关联了其他组织，请先从原组织删除");
        }
        // 判断组织是否存在
        Group group = groupService.getById(groupId);
        if (ObjectUtil.isEmpty(group)) {
            return JsonResult.fail("该组织数据不存在");
        }
        // 判断当前用户是否是该组织机构
        UserEntity loginUser = UserChacheFromToken.getUser();
        if (ObjectUtil.isEmpty(loginUser.getIsSupperAdmin()) || !loginUser.getIsSupperAdmin()) {
            if (!loginUser.getOrgId().equals(group.getOrgId())) {
                return JsonResult.fail("非法访问");
            }
        }
        // 如果该组织的成员为空，则默认第一个为组长
        List<UserEntity> userList = getUserListByGroupId(groupId);
        if (ObjectUtil.isEmpty(userList)) {
            userEntity.setIsLeader(true);
        }
        userEntity.setGroupId(groupId);
        if (!this.updateById(userEntity)) {
            throw new ServiceException("更新数据失败");
        }
        // 该用户信息发生了改变，给该用户发送通知，前端实时刷新用户信息
        Message message = new Message();
        message.setType(MessageTypeEnum.PERSONAL_MSG);
        message.setTitle("您已成功关联了【" + group.getGroupName() + "】组织");
        messageService.sendMsgToUser(userEntity.getId(), message);
        return JsonResult.ok();
    }

    @Transactional
    @Override
    public JsonResult<?> userUnboundGroup(Integer userId) {
        if (ObjectUtil.isEmpty(userId)) {
            return JsonResult.fail("缺少参数 userId");
        }
        // 判断用户是否存在
        UserEntity userEntity = this.getById(userId);
        if (ObjectUtil.isEmpty(userEntity)) {
            return JsonResult.fail("该用户数据不存在");
        }
        Integer groupId = userEntity.getGroupId();
        if (ObjectUtil.isEmpty(groupId)) {
            return JsonResult.fail("该用户没有关联组织");
        }
        // 判断组织是否存在
        Group group = groupService.getById(groupId);
        if (ObjectUtil.isEmpty(group)) {
            return JsonResult.fail("该用户所属组织数据不存在");
        }
        List<UserEntity> userList = getUserListByGroupId(groupId);
        // 如果该组织人数大于1人，该用户是组长，则把组长默认给其他人
        if (userList.size() > 1 && ObjectUtil.isNotEmpty(userEntity.getIsLeader()) && userEntity.getIsLeader()) {
            // 找出要给予组长的那个人
            List<UserEntity> restUserList = userList.stream()
                    .filter(item -> !item.getId().equals(userEntity.getId()))
                    .collect(Collectors.toList());
            UserEntity newLeader = restUserList.get(0);
            newLeader.setIsLeader(true);
            if (!this.updateById(newLeader)) {
                throw new ServiceException("新组织管理员授权失败");
            }
            // 该用户信息发生了改变，给该用户发送通知，前端实时刷新用户信息
            Message message = new Message();
            message.setType(MessageTypeEnum.PERSONAL_MSG);
            message.setTitle("您已成为【" + group.getGroupName() + "】组织的管理员");
            messageService.sendMsgToUser(newLeader.getId(), message);
        }
        userEntity.setGroupId(null);
        userEntity.setIsLeader(false);
        if (!this.updateById(userEntity)) {
            throw new ServiceException("更新用户信息失败");
        }
        // 该用户信息发生了改变，给该用户发送通知，前端实时刷新用户信息
        Message message2 = new Message();
        message2.setType(MessageTypeEnum.PERSONAL_MSG);
        message2.setTitle("您已成功从【" + group.getGroupName() + "】组织取消关联");
        messageService.sendMsgToUser(userEntity.getId(), message2);
        return JsonResult.ok();
    }

    @Transactional
    @Override
    public JsonResult<?> setGroupManager(Integer userId) {
        if (ObjectUtil.isEmpty(userId)) {
            return JsonResult.fail("缺少参数 userId");
        }
        // 判断用户是否存在
        UserEntity userEntity = this.getById(userId);
        if (ObjectUtil.isEmpty(userEntity)) {
            return JsonResult.fail("该用户数据不存在");
        }
        Integer groupId = userEntity.getGroupId();
        if (ObjectUtil.isEmpty(groupId)) {
            return JsonResult.fail("该用户没有关联组织");
        }
        // 判断组织是否存在
        Group group = groupService.getById(groupId);
        if (ObjectUtil.isEmpty(group)) {
            return JsonResult.fail("该用户所属组织数据不存在");
        }
        List<UserEntity> userList = getUserListByGroupId(groupId);
        if (ObjectUtil.isEmpty(userList)) {
            return JsonResult.fail("该用户所属组织成员数据为空");
        }
        UserEntity oldLeader = null;
        // 找出原来的组长
        Optional<UserEntity> oldLeaderOp = userList.stream()
                .filter(item -> ObjectUtil.isNotEmpty(item.getIsLeader()) && item.getIsLeader())
                .findFirst();
        if (oldLeaderOp.isPresent()) {
            oldLeader = oldLeaderOp.get();
        }
        if (ObjectUtil.isEmpty(oldLeader)) {
            return JsonResult.fail("该用户所属组织管理员数据为空");
        }
        if (oldLeader.getId().equals(userId)) {
            return JsonResult.ok();
        }
        oldLeader.setIsLeader(false);
        if (!this.updateById(oldLeader)) {
            throw new ServiceException("更新数据失败[1]");
        }
        // 该用户信息发生了改变，给该用户发送通知，前端实时刷新用户信息
        Message message = new Message();
        message.setType(MessageTypeEnum.PERSONAL_MSG);
        message.setTitle("您的【" + group.getGroupName() + "】组织的管理员身份已被撤销");
        messageService.sendMsgToUser(oldLeader.getId(), message);
        userEntity.setIsLeader(true);
        if (!this.updateById(userEntity)) {
            throw new ServiceException("更新数据失败[2]");
        }
        // 该用户信息发生了改变，给该用户发送通知，前端实时刷新用户信息
        Message message2 = new Message();
        message2.setType(MessageTypeEnum.PERSONAL_MSG);
        message2.setTitle("您已成为【" + group.getGroupName() + "】组织的管理员");
        messageService.sendMsgToUser(userEntity.getId(), message2);
        return JsonResult.ok();
    }

    /**
     * 根据组织id获取成员列表
     *
     * @param groupId 组织id
     * @return 成员列表
     */
    @Override
    public List<UserEntity> getUserListByGroupId(Integer groupId) {
        if (ObjectUtil.isEmpty(groupId)) {
            return null;
        }
        LambdaQueryWrapper<UserEntity> wrapper = Wrappers.<UserEntity>lambdaQuery()
                .eq(UserEntity::getGroupId, groupId)
                .orderByDesc(UserEntity::getIsLeader);
        return list(wrapper);
    }

    @Override
    public List<UserEntity> getMembersByLeaderId(Integer id) {
        List<UserEntity> memberList = new ArrayList<>();
        if (ObjectUtils.isEmpty(id)) {
            throw new ServiceException("参数 id 不能为空！");
        }
        UserEntity leader = this.getByIdEntity(id);
        if (ObjectUtils.isEmpty(leader)) {
            throw new ServiceException("该用户不存在");
        }
        if (!leader.getIsLeader()) {
            throw new ServiceException("该用户不是组织管理者");
        }
        Integer groupId = leader.getGroupId();
        if (ObjectUtil.isEmpty(groupId)) {
            throw new ServiceException("该用户组织ID为空");
        }
        List<UserEntity> groupMemberList = getUserListByGroupId(groupId);
        memberList = groupMemberList.stream()
                .filter(item -> !leader.getId().equals(item.getId())).collect(Collectors.toList());
        return memberList;
    }

    @Override
    public void logout() {
        Integer userId = UserChacheFromToken.getUserId();
        System.out.println("logout ===>" + userId);
        if (!ObjectUtils.isEmpty(userId)) {
            tokenUtil.removeToken(userId);
        }
    }

    /**
     * 根据组织id获取成员的组长
     *
     * @param groupId 组织id
     * @return 组长用户
     */
    public UserEntity getLeaderByGroupId(Integer groupId) {
        if (ObjectUtil.isEmpty(groupId)) {
            return null;
        }
        LambdaQueryWrapper<UserEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserEntity::getGroupId, groupId);
        wrapper.eq(UserEntity::getIsLeader, true);
        return getOne(wrapper);
    }
}
